package com.budwk.app.sys.services.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import com.alibaba.fastjson.JSONObject;
import com.budwk.app.common.config.AppException;
import com.budwk.app.sys.dto.SysUnitUpdateDTO;
import com.budwk.app.sys.enums.SysLeaderType;
import com.budwk.app.sys.enums.SysUnitType;
import com.budwk.app.sys.models.*;
import com.budwk.app.sys.services.*;
import com.budwk.app.sys.vo.UnitServiceVo;
import com.budwk.app.util.adminUtils.CommonCheckUtils;
import com.budwk.starter.common.constant.GlobalConstant;
import com.budwk.starter.common.constant.RedisConstant;
import com.budwk.starter.common.exception.BaseException;
import com.budwk.starter.common.page.PageUtil;
import com.budwk.starter.common.page.Pagination;
import com.budwk.starter.common.result.ResultCode;
import com.budwk.starter.database.service.BaseServiceImpl;
import com.budwk.starter.security.utils.SecurityUtil;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.*;
import org.nutz.dao.entity.annotation.Table;
import org.nutz.dao.sql.Criteria;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.sql.SqlCallback;
import org.nutz.dao.util.cri.SqlExpressionGroup;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.lang.random.R;
import org.nutz.lang.util.NutMap;
import org.nutz.plugins.wkcache.annotation.CacheDefaults;
import org.nutz.plugins.wkcache.annotation.CacheRemoveAll;
import org.nutz.trans.Trans;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author wizzer@qq.com
 */
@Slf4j
@IocBean(args = {"refer:dao"})
@CacheDefaults(cacheName = RedisConstant.WKCACHE + "shequ.sys_unit", isHash = false, cacheLiveTime = RedisConstant.WKCACHE_TIMEOUT)
public class SysUnitServiceImpl extends BaseServiceImpl<Sys_unit> implements SysUnitService {
    public SysUnitServiceImpl(Dao dao) {
        super(dao);
    }

    @Inject
    private SysUserService sysUserService;
    @Inject
    private SysUnitUserService sysUnitUserService;
    @Inject
    private SysGroupService sysGroupService;
    @Inject
    private SysRoleService sysRoleService;
    @Inject
    private SysDictService sysDictService;
    @Inject
    private SysLogService sysLogService;

    @Override
    @Aop(TransAop.READ_COMMITTED)
    public void save(Sys_unit unit) {
        String serviceOrderTypeStr = Joiner.on(",").join(unit.getServiceOrderTypeList());
        unit.setServiceOrderType(serviceOrderTypeStr);
        // 更新模板
        unit.setServiceTypeTemplate(unit.getServiceTypeTemplate());
        Sys_unit parentUnit = this.fetch(unit.getParentId());
        unit.setPath(getSubPath("shequ.sys_unit", "path", parentUnit.getPath()));
        unit.setParentId(unit.getParentId());
        dao().insert(unit);
        this.update(Chain.make("hasChildren", true), Cnd.where("id", "=", unit.getParentId()));
    }

    @Override
    @Aop(TransAop.READ_COMMITTED)
    public void update(Sys_unit unit, String[] leaders, String[] highers, String[] assigners) {
        String serviceOrderTypeStr = Joiner.on(",").join(unit.getServiceOrderTypeList());
        unit.setServiceOrderType(serviceOrderTypeStr);
        // 更新模板
        unit.setServiceTypeTemplate(unit.getServiceTypeTemplate());
        this.updateIgnoreNull(unit);
        this.dao().clear("shequ.sys_unit_user", Cnd.where("unitId", "=", unit.getId()));
        if (leaders != null) {
            for (String leader : leaders) {
                Sys_unit_user unitUser = new Sys_unit_user();
                unitUser.setUnitId(unit.getId());
                unitUser.setUserId(leader);
                unitUser.setLeaderType(SysLeaderType.LEADER);
                unitUser.setCreatedBy(unitUser.getUpdatedBy());
                this.dao().insert(unitUser);
            }
        }
        if (highers != null) {
            for (String higher : highers) {
                Sys_unit_user unitUser = new Sys_unit_user();
                unitUser.setUnitId(unit.getId());
                unitUser.setUserId(higher);
                unitUser.setLeaderType(SysLeaderType.HIGHER);
                unitUser.setCreatedBy(unitUser.getUpdatedBy());
                this.dao().insert(unitUser);
            }
        }
        if (assigners != null) {
            for (String assigner : assigners) {
                Sys_unit_user unitUser = new Sys_unit_user();
                unitUser.setUnitId(unit.getId());
                unitUser.setUserId(assigner);
                unitUser.setLeaderType(SysLeaderType.ASSIGNER);
                unitUser.setCreatedBy(unitUser.getUpdatedBy());
                this.dao().insert(unitUser);
            }
        }
    }

    @Override
    @Aop(TransAop.READ_COMMITTED)
    @CacheRemoveAll
    public void deleteAndChild(Sys_unit unit) {
        //dao().execute(Sqls.create("delete from shequ.sys_unit where path like @path").setParam("path", unit.getPath() + "%"));
        //dao().execute(Sqls.create("delete from shequ.sys_unit_user where unitId=@id or unitId in(SELECT id FROM shequ.sys_unit WHERE path like @path)").setParam("id", unit.getId()).setParam("path", unit.getPath() + "%"));
        //dao().execute(Sqls.create("delete from shequ.sys_role where unitId=@id or unitId in(SELECT id FROM shequ.sys_unit WHERE path like @path)").setParam("id", unit.getId()).setParam("path", unit.getPath() + "%"));
        //if (!Strings.isEmpty(unit.getParentId())) {
        //    int count = count(Cnd.where("parentId", "=", unit.getParentId()));
        //    if (count < 1) {
        //        dao().execute(Sqls.create("update shequ.sys_unit set hasChildren=0 where id=@pid").setParam("pid", unit.getParentId()));
        //    }
        //}

        // 删除单位 删除角色 上面这个方法非常不可靠，因为会造成误删的情况
        List<String> deleteIdList = Lists.newArrayList(unit.getId());
        List<String> allSubIdList = getAllSubIdList(unit.getId());
        deleteIdList.addAll(allSubIdList);

        delete(deleteIdList);

        String parentId = unit.getParentId();
        if (StringUtils.isNotBlank(parentId)) {
            Sys_unit parentUnit = fetch(parentId);
            List<String> subUnitIds = getSubUnitIds(parentId);
            parentUnit.setHasChildren(subUnitIds.size() > 0);
            update(parentUnit);
        }
    }

    @Override
    public Pagination searchUser(String username, String unitId) {
        if (Strings.isBlank(unitId)) {
            return new Pagination();
        }
        //获取本级及下一级单位的用户信息
        Sys_unit unit = this.fetch(unitId);
        String path = unit.getPath();
        Sql sql = Sqls.create("SELECT id AS VALUE,username AS label from shequ.sys_user where (unitId=@unitId or unitPath like @unitPath) $s order by username asc");
        sql.setParam("unitPath", path + "____");
        sql.setParam("unitId", unitId);
        if (Strings.isNotBlank(username)) {
            sql.setVar("s", " and (username like '%" + username + "%' or loginname like '%" + username + "%')");
        }
        return this.listPage(1, 20, sql);
    }

    @Override
    public String getMasterCompanyId(String unitId) {
        Sys_unit unit = this.fetch(unitId);
        if (unit == null) {
            throw new BaseException(ResultCode.NULL_DATA_ERROR.getMsg());
        }
        if (SysUnitType.GROUP == unit.getType() || SysUnitType.COMPANY == unit.getType()) {
            return unit.getId();
        } else if (Strings.isNotBlank(unit.getParentId())) {
            return getMasterCompanyId(unit.getParentId());
        } else {
            return "";
        }
    }

    @Override
    public String getMasterCompanyPath(String unitId) {
        Sys_unit unit = this.fetch(unitId);
        if (unit == null) {
            throw new BaseException(ResultCode.NULL_DATA_ERROR.getMsg());
        }
        if (SysUnitType.GROUP == unit.getType() || SysUnitType.COMPANY == unit.getType()) {
            return unit.getPath();
        } else if (Strings.isNotBlank(unit.getParentId())) {
            return getMasterCompanyPath(unit.getParentId());
        } else {
            return "0000";
        }
    }

    @Override
    public Sys_unit getMasterCompany(String unitId) {
        Sys_unit unit = this.fetch(unitId);
        if (unit == null) {
            throw new BaseException(ResultCode.NULL_DATA_ERROR.getMsg());
        }
        if (SysUnitType.GROUP == unit.getType() || SysUnitType.COMPANY == unit.getType()) {
            return unit;
        } else if (Strings.isNotBlank(unit.getParentId())) {
            return getMasterCompany(unit.getParentId());
        } else {
            return null;
        }
    }

    public List<String> getSubUnitIds(String parentId) {
        List<Sys_unit> list = this.query();
        //转为树形数据
        NutMap nutMap = NutMap.NEW();
        for (Sys_unit unit : list) {
            List<Sys_unit> list1 = nutMap.getList(unit.getParentId(), Sys_unit.class);
            if (list1 == null) {
                list1 = new ArrayList<>();
            }
            list1.add(unit);
            nutMap.put(Strings.sNull(unit.getParentId()), list1);
        }
        List<String> unitIds = new ArrayList<>();
        getSubTree(unitIds, nutMap, parentId, null);
        return unitIds;
    }

    private void getSubTree(List<String> treeList, NutMap nutMap, String parentId, SysUnitType unitType) {
        List<Sys_unit> subList = nutMap.getList(parentId, Sys_unit.class);
        for (Sys_unit unit : subList) {
            if (unitType != null) {
                if (unitType.equals(unit.getType())) {
                    treeList.add(unit.getId());
                }
            } else {
                treeList.add(unit.getId());
            }
            getSubTree(treeList, nutMap, unit.getId(), unitType);
        }
    }

    /**
     * 获取所有子集的数据
     *
     * @param id 父节点id
     * @return 结果
     */
    private List<String> getAllSubIdList(String id) {
        List<String> resultList = Lists.newArrayList();
        Cnd cnd = Cnd.NEW().and("parentid", "=", id);
        List<Sys_unit> subList = query(cnd);
        resultList.addAll(subList.stream().map(Sys_unit::getId).collect(Collectors.toList()));
        if (subList.size() > 0) {
            for (Sys_unit subUnit : subList) {
                resultList.addAll(getAllSubIdList(subUnit.getId()));
            }
        }

        return resultList;
    }

    @Override
    @CacheRemoveAll
    public void createCompanyExhaustive(SysUnitUpdateDTO unit, String userId) {
        // 记录日志
        sysLogService.insertUpdateLog(SecurityUtil.getUserId(), JSONObject.toJSONString(unit), Sys_unit.class.getAnnotation(Table.class).value(),
                "com.budwk.app.sys.services.impl.SysUnitServiceImpl.createCompanyExhaustive",
                "createCompanyExhaustive");
        // wzy 2023-10-19 创建单位信息 附加创建默认角色 工作任务类型字典 以及配置使用了什么模板
        // 但是这个代码是从上面createcompany来的，这个方法中使用了一些来路不明的常量，我不打算重新写 所以直接复制上面的方法了。。。

        // 判断一下名称是否相同，如果相同则提示名称重复 其次如果编码为null默认使用汉语拼音作为code
        String name = unit.getName();
        Cnd existCnd = Cnd.NEW();
        existCnd.and("name", "=", name);
        int count = count(existCnd);
        if (count > 0) throw new RuntimeException("名称重复！添加失败！");

        Trans.exec(() -> {

            String parentPath = null;
            if (unit.getParentId() != null) {
                Sys_unit parentUnit = this.fetch(unit.getParentId());
                parentPath = parentUnit.getPath();

                parentUnit.setHasChildren(true);
                update(parentUnit);
            }

            if (StringUtils.isBlank(unit.getUnitcode())) {
                unit.setUnitcode(PinyinUtil.getFirstLetter(unit.getName(), ""));
            }
            unit.setCreatedBy(SecurityUtil.getUserId());
            unit.setDisabled(false);
            unit.setLocation(0);
            unit.setHasChildren(false);
            unit.setDelFlag(false);
            unit.setPath(getSubPath("shequ.sys_unit", "path", parentPath));
            unit.setParentId(unit.getParentId());

            if (unit.getServiceOrderTypeList() != null) {
                String serviceOrderType = Joiner.on(",").join(unit.getServiceOrderTypeList());
                unit.setServiceOrderType(serviceOrderType);
            }
            insert(unit);

            //新建分组
            Sys_group group = new Sys_group();
            group.setUnitId(unit.getId());
            group.setCreatedBy(SecurityUtil.getUserId());
            group.setName(unit.getName());
            group.setUnitPath(unit.getPath());
            sysGroupService.insert(group);

            //新建普通角色
            Sys_role role = new Sys_role();
            //String uId = UUID.randomUUID().toString().replaceAll("-","");
            role.setGroupId(group.getId());
            role.setUnitId(unit.getId());
            String uIdCode = UUID.randomUUID().toString().replaceAll("-", "");
            role.setCode("publics");
            role.setDisabled(false);
            role.setCreatedBy(SecurityUtil.getUserId());
            role.setName("普通角色");
            sysRoleService.insert(role);

            String[] ids = Strings.splitIgnoreBlank("9d010f91044b4d76ad4873c3fb0b1210,b414adb6369041a6a5d0c1f7992c1b19,2e016f846b8a4489b2044cca4eb562cc,2beb430e1aa84f72bfd3a9a5732b8db2,a659196dc29243db8bd749b879d9466f,76d5b22c621c448394611c93a523368e,ccdc628c6c704e88b4d2b3312622550f");
            if (GlobalConstant.DEFAULT_SYSADMIN_ROLECODE.equals(uIdCode) && ids.length == 0) {
                throw new RuntimeException("角色权限不可为空,可能会造成无法登录系统");
            }
            sysRoleService.saveMenu(role.getId(), "PLATFORM", ids);


            Sys_role adminRole = new Sys_role();
            adminRole.setGroupId(group.getId());
            adminRole.setUnitId(unit.getId());
            String adminIdCode = UUID.randomUUID().toString().replaceAll("-", "");
            adminRole.setCode("admin");
            adminRole.setDisabled(false);
            adminRole.setCreatedBy(SecurityUtil.getUserId());
            adminRole.setName("社区管理员");
            sysRoleService.insert(adminRole);

            String[] adminMenuIds = Strings.splitIgnoreBlank("fc348d93d9454d66be5e486dbef2d6f8,3c0a52058051471e991d6a0a73572200,3044cbbf64d34ad1a139a3cb3034f885,451b85d1d84449e9aedd7fc7ab63c42b,ed5f07e5d5154826b3381a75fe3b0747,9d010f91044b4d76ad4873c3fb0b1210,b414adb6369041a6a5d0c1f7992c1b19,2e016f846b8a4489b2044cca4eb562cc,2beb430e1aa84f72bfd3a9a5732b8db2,a659196dc29243db8bd749b879d9466f,76d5b22c621c448394611c93a523368e,ccdc628c6c704e88b4d2b3312622550f");
            if (GlobalConstant.DEFAULT_SYSADMIN_ROLECODE.equals(adminIdCode) && adminMenuIds.length == 0) {
                throw new RuntimeException("超级管理员角色权限不可为空,可能会造成无法登录系统");
            }
            sysRoleService.saveMenu(adminRole.getId(), "PLATFORM", adminMenuIds);
        });
    }

    @Override
    @CacheRemoveAll
    public void updateCompanyExhaustive(SysUnitUpdateDTO unit, String userId) {
        List<UnitServiceVo> serviceTypeTemplate = unit.getServiceTypeTemplate();
        String name = unit.getName();
        Cnd existCnd = Cnd.NEW();
        existCnd.and("name", "=", name).and("id", "!=", unit.getId());
        int count = count(existCnd);
        if (count > 0) throw new RuntimeException("名称重复!修改失败!");

        String unitCode = unit.getUnitcode();
        Cnd codeExistCnd = Cnd.NEW();
        codeExistCnd.and("unitcode", "=", unitCode).and("id", "!=", unit.getId());
        int codeCount = count(codeExistCnd);
        if (codeCount > 0) throw new RuntimeException("code重复!修改失败!");

        String serviceOrderTypeStr = Joiner.on(",").join(unit.getServiceOrderTypeList());
        unit.setServiceOrderType(serviceOrderTypeStr);
        updateIgnoreNull(unit);
        log.info("updateCompanyExhaustive serviceTypeTemplate: {}", serviceTypeTemplate);
        Sys_unit sysUnit = this.fetch(unit.getId());
        sysUnit.setServiceTypeTemplate(serviceTypeTemplate);
        this.update(sysUnit);
    }

    /**
     * 通过用户5级信息获取单位信息
     *
     * @param sysUser
     * @return
     */
    @Override
    public Sys_unit getUnitInfoByArea(Sys_user sysUser) {
        if (Strings.isBlank(sysUser.getProvince())
                || Strings.isBlank(sysUser.getCity())
                || Strings.isBlank(sysUser.getDistrict())
                || Strings.isBlank(sysUser.getCounty())
                || Strings.isBlank(sysUser.getCommunity())) {
            return new Sys_unit();
        }
        Cnd cnd = Cnd.NEW();
        cnd.and(Sys_unit::getProvince, "=", sysUser.getProvince());
        cnd.and(Sys_unit::getCity, "=", sysUser.getCity());
        cnd.and(Sys_unit::getDistrict, "=", sysUser.getDistrict());
        cnd.and(Sys_unit::getCounty, "=", sysUser.getCounty());
        cnd.and(Sys_unit::getCommunity, "=", sysUser.getCommunity());
        return this.fetch(cnd);
    }

    /**
     * 获取单位列表信息（后台管理系统）
     *
     * @param bean
     * @param pageNo
     * @param pageSize
     * @param pageOrderName
     * @param pageOrderBy
     * @return
     */
    @Override
    public Pagination listUnitForAdmin(SysUnitUpdateDTO bean, int pageNo, int pageSize, String pageOrderName, String pageOrderBy) {
        Cnd cnd = Cnd.NEW();
        if (StringUtils.isNotBlank(bean.getProvince())) {
            cnd.and("province", "=", bean.getProvince());
        }
        if (StringUtils.isNotBlank(bean.getCity())) {
            cnd.and("city", "=", bean.getCity());
        }
        if (StringUtils.isNotBlank(bean.getDistrict())) {
            cnd.and("district", "=", bean.getDistrict());
        }
        if (StringUtils.isNotBlank(bean.getCounty())) {
            cnd.and("county", "=", bean.getCounty());
        }
        if (StringUtils.isNotBlank(bean.getCommunity())) {
            cnd.and("community", "=", bean.getCommunity());
        }

        if (Strings.isNotBlank(bean.getServiceOrderType())) {
            cnd.and("service_order_type", "like", "%" + bean.getServiceOrderType() + "%");
        }
        if (Strings.isNotBlank(pageOrderName) && Strings.isNotBlank(pageOrderBy)) {
            cnd.orderBy(pageOrderName, PageUtil.getOrder(pageOrderBy));
        }
        return this.listPage(pageNo, pageSize, cnd);
    }

    /**
     * 修改单位信息（后台管理系统）
     *
     * @param unitDto
     */
    @Override
    @Aop(TransAop.READ_COMMITTED)
    @CacheRemoveAll
    public String updateUnitForAdmin(SysUnitUpdateDTO unitDto) {
        // 记录日志
        sysLogService.insertUpdateLog(SecurityUtil.getUserId(), JSONObject.toJSONString(unitDto), Sys_unit.class.getAnnotation(Table.class).value(),
                "com.budwk.app.sys.services.impl.SysUnitServiceImpl.updateUnitForAdmin",
                "updateUnitForAdmin");
        SysUnitUpdateDTO unit = new SysUnitUpdateDTO();
        BeanUtil.copyProperties(unitDto, unit);
        if (Strings.isNotBlank(unit.getProvince())
                && Strings.isNotBlank(unit.getCity())
                && Strings.isNotBlank(unit.getDistrict())
                && Strings.isNotBlank(unit.getCounty())
                && Strings.isNotBlank(unit.getCommunity())) {
            unit.setProvince(unit.getProvince().trim());
            unit.setCity(unit.getCity().trim());
            unit.setDistrict(unit.getDistrict().trim());
            unit.setCounty(unit.getCounty().trim());
            unit.setCommunity(unit.getCommunity().trim());
        } else {
            throw new AppException("五级区域不能为空！");
        }

        if (Strings.isBlank(unit.getId())) {
            return ResultCode.NULL_DATA_ERROR.getMsg();
        }
        Sys_unit sysUnit = fetch(unit.getId());
        if (ObjectUtil.isEmpty(sysUnit)) {
            return ResultCode.USER_NOT_FOUND.getMsg();
        }
        String serviceOrderTypeStr = Joiner.on(",").join(unit.getServiceOrderTypeList());

        // 检查单位是否存在，存在则抛错
        Sys_user sysUser = new Sys_user();
        sysUser.setProvince(unit.getProvince());
        sysUser.setCity(unit.getCity());
        sysUser.setDistrict(unit.getDistrict());
        sysUser.setCounty(unit.getCounty());
        sysUser.setCommunity(unit.getCommunity());
        Sys_unit sysUnitArea = this.getUnitInfoByArea(sysUser);
        if (ObjectUtil.isNotEmpty(sysUnitArea) && !sysUnitArea.getId().equals(unit.getId())) {
            return ResultCode.HAVE_DATA_ERROR.getMsg();
        }
        unit.setServiceOrderType(serviceOrderTypeStr);
        unit.setUpdatedBy(SecurityUtil.getUserId());
        unit.setUpdatedAt(new Date().getTime());
        if (ObjectUtil.isEmpty(unit.getType())) {
            unit.setType(SysUnitType.GROUP);
        }
        unit.setName(String.format("%s%s%s%s%s", unit.getProvince(), unit.getCity(), unit.getDistrict(), unit.getCounty(), unit.getCommunity()));
        this.updateIgnoreNull(unit);

        // 更新模板
        List<UnitServiceVo> serviceTypeTemplate = unit.getServiceTypeTemplate();
        log.info("updateCompanyExhaustive serviceTypeTemplate: {}", serviceTypeTemplate);
        Sys_unit sysUnit1 = this.fetch(unit.getId());
        sysUnit1.setServiceTypeTemplate(serviceTypeTemplate);
        this.updateIgnoreNull(sysUnit1);
        return ResultCode.SUCCESS.getMsg();
    }

    @Override
    @Aop(TransAop.READ_COMMITTED)
    @CacheRemoveAll
    public String deleteForAdmin(String id) {
        if (Strings.isBlank(id)) {
            return ResultCode.USER_NOT_FOUND.getMsg();
        }
        // 记录日志
        sysLogService.insertDelLog(SecurityUtil.getUserId(), JSONObject.toJSONString(id), Sys_unit.class.getAnnotation(Table.class).value(),
                "com.budwk.app.sys.services.impl.SysUnitServiceImpl.deleteForAdmin",
                "deleteForAdmin");
        this.delete(id);
        return ResultCode.SUCCESS.getMsg();
    }

    @Override
    public List<String> queryCommunityList(SysUnitUpdateDTO bean) {
        if (StringUtils.isEmpty(bean.getProvince())
                && StringUtils.isEmpty(bean.getCity())
                && StringUtils.isEmpty(bean.getDistrict())
                && StringUtils.isEmpty(bean.getCounty())) {
            throw new AppException(ResultCode.PARAM_ERROR.getMsg());
        }
        StringBuffer sb = new StringBuffer();
        sb.append("SELECT DISTINCT community FROM shequ.\"sys_unit\" WHERE 1 = 1 ");
        if (StringUtils.isNotEmpty(bean.getProvince())) {
            sb.append(" AND province = '").append(bean.getProvince()).append("'");
        }
        if (StringUtils.isNotEmpty(bean.getCity())) {
            sb.append(" AND city = '").append(bean.getCity()).append("'");
        }
        if (StringUtils.isNotEmpty(bean.getDistrict())) {
            sb.append(" AND district = '").append(bean.getDistrict()).append("'");
        }
        if (StringUtils.isNotEmpty(bean.getCounty())) {
            sb.append(" AND county = '").append(bean.getCounty()).append("'");
        }
        Sql sql = Sqls.create(sb.toString());
        sql.setCallback(new SqlCallback() {
            @Override
            public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException {
                ResultSetMetaData metaData = rs.getMetaData();
                int columnCount = metaData.getColumnCount();
                List<String> resultList = new ArrayList<String>();
                while (rs.next()) {
                    for (int i = 0; i < columnCount; i++) {
                        String community = rs.getString("community");
                        if ("直属".equals(community) || StringUtils.isEmpty(community)) {
                            continue;
                        }
                        resultList.add(community);
                    }
                }
                return resultList;
            }
        });
        sysUserService.execute(sql);
        return sql.getList(String.class);
    }

    @Override
    @Aop(TransAop.READ_COMMITTED)
    @CacheRemoveAll
    public Integer batchUpdateForAdmin(List<String> ids, SysUnitUpdateDTO bean) {
        if (ObjectUtil.isEmpty(ids) || ids.size() <= 0) {
            throw new AppException(ResultCode.PARAM_ERROR.getMsg());
        }
        // 记录日志
        sysLogService.insertUpdateLog(SecurityUtil.getUserId(), JSONObject.toJSONString(bean), Sys_unit.class.getAnnotation(Table.class).value(),
                "com.budwk.app.sys.services.impl.SysUnitServiceImpl.batchUpdateForAdmin",
                "batchUpdateForAdmin");
        if (ObjectUtil.isEmpty(bean.getServiceOrderTypeList()) || bean.getServiceOrderTypeList().size() <= 0) {
            throw new AppException(ResultCode.PARAM_ERROR.getMsg());
        }
        List<String> sortedServiceTypes = bean.getServiceOrderTypeList().stream()
                .sorted(new Comparator<String>() {
                    @Override
                    public int compare(String o1, String o2) {
                        return CommonCheckUtils.getPinyinFirstLetter(o1).compareTo(CommonCheckUtils.getPinyinFirstLetter(o2));
                    }
                }).collect(Collectors.toList());
        String serviceOrderTypes = Joiner.on(",").join(sortedServiceTypes);
        Cnd cnd = Cnd.NEW();
        cnd.and(Sys_unit::getId, "IN", ids);
        int updateNum = count(cnd);
        if (0 >= updateNum) {
            throw new AppException(ResultCode.NULL_DATA_ERROR.getMsg());
        }
        List<UnitServiceVo> serviceTypeTemplate = bean.getServiceTypeTemplate();
        return update(Chain.make("serviceOrderType", serviceOrderTypes).add("serviceTypeTemplate", serviceTypeTemplate), Cnd.where(Sys_unit::getId, "IN", ids));
    }

    @Override
    public void unitDataClean(String level) {
        /**
         * level = 1 省
         * level = 2 市
         * level = 3 区/县
         * level = 4 乡、镇、街道
         * level = 5 社区、村
         */
        // 1. 查询出各个区域下的单位数据
        Cnd cnd = Cnd.NEW();
        if ("1".equals(level)) {
            cnd.and(Sys_unit::getProvince, "!=", "直属")
                    .and(Sys_unit::getCity, "=", "直属")
                    .and(Sys_unit::getDistrict, "=", "直属")
                    .and(Sys_unit::getCounty, "=", "直属")
                    .and(Sys_unit::getCommunity, "=", "直属");
        } else if ("2".equals(level)) {
            cnd.and(Sys_unit::getProvince, "!=", "直属")
                    .and(Sys_unit::getCity, "!=", "直属")
                    .and(Sys_unit::getDistrict, "=", "直属")
                    .and(Sys_unit::getCounty, "=", "直属")
                    .and(Sys_unit::getCommunity, "=", "直属");
        } else if ("3".equals(level)) {
            cnd.and(Sys_unit::getProvince, "!=", "直属")
                    .and(Sys_unit::getCity, "!=", "直属")
                    .and(Sys_unit::getDistrict, "!=", "直属")
                    .and(Sys_unit::getCounty, "=", "直属")
                    .and(Sys_unit::getCommunity, "=", "直属");
        } else if ("4".equals(level)) {
            cnd.and(Sys_unit::getProvince, "!=", "直属")
                    .and(Sys_unit::getCity, "!=", "直属")
                    .and(Sys_unit::getDistrict, "!=", "直属")
                    .and(Sys_unit::getCounty, "!=", "直属")
                    .and(Sys_unit::getCommunity, "=", "直属");
        } else if ("5".equals(level)) {
            cnd.and(Sys_unit::getProvince, "!=", "直属")
                    .and(Sys_unit::getCity, "!=", "直属")
                    .and(Sys_unit::getDistrict, "!=", "直属")
                    .and(Sys_unit::getCounty, "!=", "直属")
                    .and(Sys_unit::getCommunity, "!=", "直属");
        }
        //cnd.and(Sys_unit::getParentId, "is", null);
        List<Sys_unit> sysUnits = query(cnd);
        sysUnits.forEach(sysUnit -> {
            Sys_unit sysUnit1 = new Sys_unit();
            Cnd cnd1 = Cnd.NEW();
            Criteria cri = Cnd.cri();
            SqlExpressionGroup criSql = cri.where();
            if ("2".equals(level)) {
                String areaName = sysUnit.getProvince();
                SqlExpressionGroup community1 = Cnd.exps("name", "=", areaName + "直属直属直属直属");
                SqlExpressionGroup community2 = Cnd.exps("name", "=", areaName);
                criSql.and(community1).or(community2);
            } else if ("3".equals(level)) {
                String areaName = sysUnit.getProvince() + sysUnit.getCity();
                SqlExpressionGroup community1 = Cnd.exps("name", "=", areaName + "直属直属直属");
                SqlExpressionGroup community2 = Cnd.exps("name", "=", areaName);
                criSql.and(community1).or(community2);
            } else if ("4".equals(level)) {
                String areaName = sysUnit.getProvince() + sysUnit.getCity() + sysUnit.getDistrict();
                SqlExpressionGroup community1 = Cnd.exps("name", "=", areaName + "直属直属");
                SqlExpressionGroup community2 = Cnd.exps("name", "=", areaName);
                criSql.and(community1).or(community2);
            } else if ("5".equals(level)) {
                String areaName = sysUnit.getProvince() + sysUnit.getCity() + sysUnit.getDistrict() + sysUnit.getCounty();
                SqlExpressionGroup community1 = Cnd.exps("name", "=",  areaName + "直属");
                SqlExpressionGroup community2 = Cnd.exps("name", "=", areaName);
                criSql.and(community1).or(community2);
            }
            sysUnit1 = fetch(cri);
            if (null != sysUnit1) {
                Sys_unit sysUnitUpdate = new Sys_unit();
                BeanUtil.copyProperties(sysUnit, sysUnitUpdate);
                sysUnitUpdate.setParentId(sysUnit1.getId());
                log.info("update-unit-update---{}", sysUnitUpdate.toJsonString());
                updateIgnoreNull(sysUnitUpdate);
            } /*else {
                Sys_unit sysUnitInsert = new Sys_unit();
                BeanUtil.copyProperties(sysUnit, sysUnitInsert);
                sysUnitInsert.setId(R.UU32());
                sysUnitInsert.setType(SysUnitType.UNIT);
                String areaName = sysUnit.getProvince() + sysUnit.getCity() + sysUnit.getDistrict() + sysUnit.getCounty();
                if (areaName.endsWith("街道")) {
                    areaName += "办事处";
                } else {
                    areaName += "政府";
                }
                sysUnitInsert.setName(areaName);
                sysUnitInsert.setUnitcode(PinyinUtil.getFirstLetter(sysUnitInsert.getName(), ""));
                sysUnitInsert.setServiceOrderType("");
                sysUnitInsert.setSafetycheckaction(null);
                sysUnitInsert.setServiceTypeTemplate(null);
                sysUnitInsert.setServiceOrderTypeList(null);
                log.info("update-unit-null-insert---{}", sysUnitInsert.toJsonString());
                this.dao().insert(sysUnitInsert);

                Sys_unit sysUnitUpdate = new Sys_unit();
                BeanUtil.copyProperties(sysUnit, sysUnitUpdate);
                sysUnitUpdate.setParentId(sysUnitInsert.getId());
                log.info("update-unit-null-update---{}", sysUnitUpdate.toJsonString());
                updateIgnoreNull(sysUnitUpdate);
            }*/
        });

    }


    @Override
    public void unitDataCleanPath(String id) {
        /**
         * level = 1 省
         * level = 2 市
         * level = 3 区/县
         * level = 4 乡、镇、街道
         * level = 5 社区、村
         */
        // 1. 查询出各个区域下的单位数据
        Cnd cnd = Cnd.NEW();
        cnd.and(Sys_unit::getCommunity, "=","直属");
        cnd.and(Sys_unit::getCounty, "!=","直属");
        cnd.and(Sys_unit::getParentId, "is not",null);
        List<Sys_unit> sysUnits = query(cnd);
        for (int i = 0; i < sysUnits.size(); i++) {
            log.info("path1=== {}, {}", sysUnits.get(i).getPath(), sysUnits.get(i).getId());
            List<Sys_unit> sysUnits1 = query(Cnd.where(Sys_unit::getParentId, "=", sysUnits.get(i).getId()));
            for (int j = 0; j < sysUnits1.size(); j++) {
                String path = sysUnits.get(i).getPath();
                int jpp = j +1;
                if (jpp < 10) {
                    path = path + "000" + String.valueOf(jpp);
                } else if (jpp >= 10 && jpp < 100) {
                    path = path + "00" + String.valueOf(jpp);
                } else  if (jpp >= 100 && jpp < 1000) {
                    path = path + "0" + String.valueOf(jpp);
                }
                log.info("path2=== {}, {}", path, sysUnits1.get(j).getId());
                this.update(Chain.make("path", path), Cnd.where("id", "=", sysUnits1.get(j).getId()));
            }
        }
    }

    @Override
    public void unitDataCleanHasChild(String level) {
        /**
         * level = 1 省
         * level = 2 市
         * level = 3 区/县
         * level = 4 乡、镇、街道
         * level = 5 社区、村
         */
        // 1. 查询出各个区域下的单位数据
        Cnd cnd = Cnd.NEW();
        if ("1".equals(level)) {
            cnd.and(Sys_unit::getProvince, "!=", "直属")
                    .and(Sys_unit::getCity, "=", "直属")
                    .and(Sys_unit::getDistrict, "=", "直属")
                    .and(Sys_unit::getCounty, "=", "直属")
                    .and(Sys_unit::getCommunity, "=", "直属");
        } else if ("2".equals(level)) {
            cnd.and(Sys_unit::getProvince, "!=", "直属")
                    .and(Sys_unit::getCity, "!=", "直属")
                    .and(Sys_unit::getDistrict, "=", "直属")
                    .and(Sys_unit::getCounty, "=", "直属")
                    .and(Sys_unit::getCommunity, "=", "直属");
        } else if ("3".equals(level)) {
            cnd.and(Sys_unit::getProvince, "!=", "直属")
                    .and(Sys_unit::getCity, "!=", "直属")
                    .and(Sys_unit::getDistrict, "!=", "直属")
                    .and(Sys_unit::getCounty, "=", "直属")
                    .and(Sys_unit::getCommunity, "=", "直属");
        } else if ("4".equals(level)) {
            cnd.and(Sys_unit::getProvince, "!=", "直属")
                    .and(Sys_unit::getCity, "!=", "直属")
                    .and(Sys_unit::getDistrict, "!=", "直属")
                    .and(Sys_unit::getCounty, "!=", "直属")
                    .and(Sys_unit::getCommunity, "=", "直属");
        } else if ("5".equals(level)) {
            cnd.and(Sys_unit::getProvince, "!=", "直属")
                    .and(Sys_unit::getCity, "!=", "直属")
                    .and(Sys_unit::getDistrict, "!=", "直属")
                    .and(Sys_unit::getCounty, "!=", "直属")
                    .and(Sys_unit::getCommunity, "!=", "直属");
        }
        List<Sys_unit> sysUnits = query(cnd);
        sysUnits.forEach(sysUnit -> {
            int childNum = this.count(Cnd.where("parentid", "=", sysUnit.getId()));
            if (childNum>0){
                this.update(Chain.make("haschildren", true), Cnd.where("id", "=", sysUnit.getId()));
            }
        });
    }

    @Override
    public Sys_unit queryUnitTree(String unitId, List<Sys_user> allUnitUser) {
        List<Sys_unit> unitList = this.query();
        Sys_unit unit = this.fetch(unitId);
        if (unit == null) {
            return null;
        }
        if (allUnitUser == null) allUnitUser = new ArrayList<>();
        List<Sys_user> users = sysUserService.query();
        List<Sys_user> userList = users.stream().filter(e -> unit.getId().equals(e.getUnitId())).collect(Collectors.toList());
        allUnitUser.addAll(userList);
        unit.setUsers(userList);
        return getTrees(unit, unitList, users, allUnitUser);
    }

    /**
     * 递归遍历查询数
     * @param node
     * @param list
     * @return
     */
    public Sys_unit getTrees(Sys_unit node, List<Sys_unit> list, List<Sys_user> users, List<Sys_user> allUnitUser) {
        String value = node.getId();
        List<Sys_unit> childs = null;
        Iterator<Sys_unit> iterator = list.iterator();
        while (iterator.hasNext()) {
            Sys_unit m = iterator.next();
            if(value.equals(m.getParentId())){
                childs = node.getChildren();
                if(childs == null) {
                    childs = new ArrayList<>();
                }
                List<Sys_user> userList = users.stream().filter(e -> m.getId().equals(e.getUnitId())).collect(Collectors.toList());
                m.setUsers(userList);
                allUnitUser.addAll(userList);
                childs.add(m);
                iterator.remove();
                node.setChildren(childs);
            }
        }
        if(childs != null && !childs.isEmpty() && list !=null && !list.isEmpty()){
            Iterator<Sys_unit> iterator2 = childs.iterator();
            while(iterator2.hasNext()){
                Sys_unit next = iterator2.next();
                getTrees(next,list, users, allUnitUser);
            }
        }
        return node;
    }
}
